package fastdfs2

import (
	"container/list"
	"errors"
	"fmt"
	"github.com/astaxie/beego/httplib"
	"runtime"
	"strconv"
	"sync"
)

type UploadParams struct {
	Fs string  //go-fastdns 上传地址
	fileMapAll []map[string]string  //定义全局变量返回数据
	FileArr []string //传入的数组参数
	errorNum int
	successNum int
	queue *Queue
}

func (u *UploadParams)UploadAll() []map[string]string {
	FileArr := u.FileArr
	var ch = make(chan int,20)
	num := len(FileArr)
	for i := 0; i < num; i++ {
		go u.upload(FileArr[i],i,ch) //子协程上传文件
	}
	for i := 0; i < num; i++ {
		<- ch
	}
	fmt.Println("文件上传成功数为:" + strconv.Itoa(u.successNum) + "！")
	return u.fileMapAll
}

/**
go-fastdns文件上传
src 文件路径
DeferFunc 协程函数 wg.Done 进行数量减1
*/
func (u *UploadParams)upload(src string,i int,ch chan int) {
	defer func() {
		ch <- i
	}()
	var obj interface{}
	req := httplib.Post(u.Fs)
	req.PostFile("file", src) //文件路径
	req.Param("output", "json")
	req.Param("scene", "")
	req.Param("path", "")
	req.ToJSON(&obj)

	//fmt.Println(num)
	if obj == nil {
		u.errorNum++ //上传失败，进行错误计数
		//if u.errorNum >= 10 {
		//	//fmt.Println("文件上传失败数为:" + strconv.Itoa(u.errorNum) + "，停止上传！")
		//	//os.Exit(1)
		//}else{
		//	fmt.Println("出错编号和出错路径：",i,src)
		//	//u.FileArr = append(u.FileArr,src)
		//	u.queue.Push(src)
		//	fmt.Println("出错重新添加，显示数组：",u.queue.Show())
		//	runtime.Goexit() //协程终止
		//}
		//fmt.Println("出错编号和出错路径：",i,src)
		//u.FileArr = append(u.FileArr,src)
		u.queue.Push(src)
		fmt.Println("出错重新添加，显示数组：",u.queue.Show())
		runtime.Goexit() //协程终止
	}
	u.successNum++
	//fmt.Println(i,u.successNum,u.errorNum)
	res := obj.(map[string]interface{})
	res2 := mapInterfaceToMapString(res)
	fileMap := make(map[string]string)
	for key, value := range res2 {
		switch key {
		case "domain":
			fileMap["domain"] = value
		case "md5":
			fileMap["md5"] = value
		case "mtime":
			fileMap["mtime"] = value
		case "path":
			fileMap["path"] = value
		case "scene":
			fileMap["scene"] = value
		case "size":
			fileMap["size"] = value
		case "url":
			fileMap["url"] = value
		}
	}
	u.fileMapAll = append(u.fileMapAll, fileMap) //子协程处理的结果合并到全局变量中

}

// map[string]interface{} 转换成map[string]string
func mapInterfaceToMapString(m map[string]interface{}) map[string]string {
	ret := make(map[string]string, len(m))
	for k, v := range m {
		ret[k] = fmt.Sprint(v)
	}
	return ret
}

//=======================
type Queue struct {
	list *list.List
	mutex sync.Mutex
}

func GetQueue() *Queue {
	return &Queue{
		list:list.New(),
	}
}

func (queue *Queue) Push(data interface{}) {
	if data == nil {
		return
	}
	queue.mutex.Lock()
	defer queue.mutex.Unlock()
	queue.list.PushBack(data)
}

func (queue *Queue) Pop() (interface{}, error) {
	queue.mutex.Lock()
	defer queue.mutex.Unlock()
	if element := queue.list.Front(); element != nil {
		queue.list.Remove(element)
		return element.Value, nil
	}
	return nil, errors.New("pop failed")
}

func (queue * Queue) Clear() {
	queue.mutex.Lock()
	defer queue.mutex.Unlock()
	for element := queue.list.Front(); element != nil; {
		elementNext := element.Next()
		queue.list.Remove(element)
		element = elementNext
	}
}

func (queue *Queue) Len() int {
	return queue.list.Len()
}

func (queue *Queue) Show() []string {
	var a = []string{}
	for item := queue.list.Front(); item != nil; item = item.Next() {
		//fmt.Println(item.Value)
		a = append(a,item.Value.(string))
	}
	return a

}

func (u *UploadParams) QueueUploadAll() {
	//queue := u.queue //声明队列
	//将数据写入队列
	for _,src := range u.FileArr {
		u.queue.Push(src)
	}
	ch := make(chan int,10) //缓冲通道声明

	for true {
		FileArr := u.queue.Show() //获取所有文件
		fmt.Println("动态数组：",len(FileArr),FileArr)
		if len(FileArr) != 0 {
			for i := 0; i < len(FileArr); i++ {
				src := FileArr[i] //删除前变量存储
				u.queue.Pop() //将成功的进行删除
				//fmt.Println(src)
				go u.upload(src,i,ch)
			}
			for i := 0; i < len(FileArr); i++ {
				<- ch
			}
			//for i := range ch {
			//	fmt.Println(i)
			//}
			if u.errorNum >= 100 {
				fmt.Println("出错次数大于100：退出执行",u.successNum,u.errorNum)
				break
			}

		}else{
			fmt.Println("数组处理完毕！")
			break
		}
	}
	//fmt.Println(queue.Show())
}
